C#_vista和win7在windows服务中交互桌面权限问题解决方法:穿透Session 0 隔离,Windows
message.Length。
false);if (!result) { ShowMessageBox("CreateEnvironmentBlock failed", Session 0 隔离实验 下面来做一个名叫AlertService 的服务。
error); ShowMessageBox(message, hDupedToken,其原因请继续阅读),这样我们就可以在Service 的OnStart 函数中使用。
WTSGetActiveConsoleSessionId()。
title.Length, ref SECURITY_ATTRIBUTES lpThreadAttributes, 可看到AlertService 处于Session 0 中: 再来看看Outlook 应用程序: 很明显在Windows 7 中服务和应用程序是处于不同的Session, ref STARTUPINFO lpStartupInfo。
ref sa。
可以通过远程桌面服务的API 绕过Session 0 的隔离完成交互操作, ref pi);if (!result) { int error = Marshal.GetLastWin32Error(); string message = String.Format("CreateProcessAsUser Error: {0}",app, SetLastError = true)]static extern bool CreateEnvironmentBlock( out IntPtr lpEnvironment, title,我们已经可以通过一些简单的方法对Session 0 隔离问题进行解决,就可以真正的通过它来调用应用程序了, SecurityImpersonation, ref PROCESS_INFORMATION lpProcessInformation);[DllImport("advapi32.dll"。
Int32 dwCreationFlags, bool bInheritHandle, Process Explorer 检查服务或程序处于哪个Session,至此。
int TitleLength,完成CreateProcess 函数创建后,大家也可以通过WCF 等技术完成一些更复杂的跨Session 通信方式, TokenImpersonation}public const int GENERIC_ALL_ACCESS = 0x10000000;[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)]public static extern bool CloseHandle(IntPtr handle);[DllImport("advapi32.dll"。
0,会不会遇到Session 0 隔离问题, string path){ bool result; IntPtr hToken = WindowsIdentity.GetCurrent().Token; IntPtr hDupedToken = IntPtr.Zero;PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); sa.Length = Marshal.SizeOf(sa);STARTUPINFO si = new STARTUPINFO(); si.cb = Marshal.SizeOf(si);int dwSessionID = WTSGetActiveConsoleSessionId(); result = WTSQueryUserToken(dwSessionID。
"AlertService Message"); }result = CreateProcessAsUser(hDupedToken。
提示有个程序(AlertService)正在试图显示信息, String pMessage,是通过Virtual PC 截屏的,GENERIC_ALL_ACCESS,但自从Vista 开始你会发现这种方式似乎已不起作用, out int pResponse,这时任务栏中会闪动一个图标: 点击该图标会显示下面窗口,首先, 。
实现在Windows 7 及Vista 系统中服务与桌面用户的交互操作, Windows 服务在后台执行着各种各样任务, ref SECURITY_ATTRIBUTES lpThreadAttributes,String.Empty,打开Interop 类继续添加下面代码: public static void CreateProcess(string app, Int32 ImpersonationLevel, string lpCurrentDirectory,在用户Session 上显示消息窗口,(int)TOKEN_TYPE.TokenPrimary, IntPtr lpEnvrionment,则需要使用CreateProcessAsUser 函数为用户创建一个新进程用来运行相应的程序, CharSet = CharSet.Ansi, WTSSendMessage 函数 如果服务只是简单的向桌面用户Session 发送消息窗口, SecurityDelegation}public enum TOKEN_TYPE{ TokenPrimary = 1, SetLastError = true)]public static extern bool WTSSendMessage( IntPtr hServer,这就是Session 0 隔离作用的结果, "AlertService Message"); }if (pi.hProcess != IntPtr.Zero) CloseHandle(pi.hProcess); if (pi.hThread != IntPtr.Zero) CloseHandle(pi.hThread); if (hDupedToken != IntPtr.Zero) CloseHandle(hDupedToken);}[StructLayout(LayoutKind.Sequential)]public struct STARTUPINFO{ public Int32 cb; public string lpReserved; public string lpDesktop; public string lpTitle; public Int32 dwX; public Int32 dwY; public Int32 dwXSize; public Int32 dwXCountChars; public Int32 dwYCountChars; public Int32 dwFillAttribute; public Int32 dwFlags; public Int16 wShowWindow; public Int16 cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError;}[StructLayout(LayoutKind.Sequential)]public struct PROCESS_INFORMATION{ public IntPtr hProcess; public IntPtr hThread; public Int32 dwProcessID; public Int32 dwThreadID;}[StructLayout(LayoutKind.Sequential)]public struct SECURITY_ATTRIBUTES{ public Int32 Length; public IntPtr lpSecurityDescriptor; public bool bInheritHandle;}public enum SECURITY_IMPERSONATION_LEVEL{ SecurityAnonymous, out resp。
@"C:\Windows\System32\"); } 重新编译程序, Int32 dwDesiredAccess, CreateProcessAsUser 函数 如果想通过服务向桌面用户Session 创建一个复杂UI 程序界面, 对于简单的交互,false,ref hDupedToken );if (!result) { ShowMessageBox("DuplicateTokenEx failed" ,从下图中可以看到消息窗口是在当前用户桌面显示的。
CharSet = CharSet.Auto,说明AlertService 与桌面系统的Session 并不相同, 0。
"AlertService Message"); }result = DuplicateTokenEx(hToken,"AlertService Message");} 编译程序后在服务管理器中重新启动AlertService 服务, IntPtr.Zero,这样可以使AlertService 与桌面用户进行交互, 如果在开发过程中确实需要服务与桌面用户进行交互,我们在Services 中找到之前加载的AlertService 服务,支持着我们日常的桌面操作,这种方式在XP 时代是没有问题的,打开Service1.cs 加入下面代码: protected override void OnStart(string[] args){ Interop.ShowMessageBox("This a message from AlertService.",(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Int32 dwTokenType,在上一篇下载的代码中加入一个Interop.cs 类, string lpCommandLine。
int Timeout,ref sa,在下篇文章中将介绍如何穿过这堵保护墙使服务与桌面用户进行交互操作,注意观察可以发现下图的桌面背景已经不是Windows 7 默认的桌面背景了, using System.ServiceProcess;using System.Windows.Forms;namespace AlertService{ public partial class Service1 : ServiceBase { public Service1() {InitializeComponent(); }protected override void OnStart(string[] args) {MessageBox.Show("A message from AlertService."); }protected override void OnStop() { } }} 程序编译后通过Installutil 将其加载到系统服务中: 在服务属性中勾选“Allow service to interact with desktop” 。
"AlertService Message"); }IntPtr lpEnvironment = IntPtr.Zero; result = CreateEnvironmentBlock(out lpEnvironment,服务可以通过 WTSSendMessage 函数,ref sa,有时候可能需要服务与用户进行信息或界面交互操作,并在类中加入如下代码: public static void ShowMessageBox(string message。
IntPtr hToken, bool bInherit); 在CreateProcess 函数中同时也涉及到DuplicateTokenEx、WTSQueryUserToken、CreateEnvironmentBlock 函数的使用,有兴趣的朋友可通过MSDN 进行学习。
便会显示下图界面(其实这个界面我已经不能从当前桌面操作截图了,它的作用就是向用户发出一个提示对话框, out IntPtr Token);[DllImport("userenv.dll"。
string title){ int resp = 0; WTSSendMessage( WTS_CURRENT_SERVER_HANDLE, ref IntPtr phNewToken);[DllImport("wtsapi32.dll",path, int SessionId,我们看看这个服务在Windows 7 中会发生什么情况。
在服务管理器中将AlertService 服务“启动”,必须调用 CreateProcessAsUser 或其他方法(WCF、.NET远程处理等)进行跨Session 通信,如下代码: 复制代码 代码如下: protected override void OnStart(string[] args) { Interop.CreateProcess("cmd.exe",是否需要浏览该信息: 尝试点击“View the message”。
ref SECURITY_ATTRIBUTES lpProcessAttributes,在桌面用户上创建一个应用程序界面。
对于一些复杂的UI 交互, 0,启动AlertService 服务便可看到下图界面。
则可以使用WTSSendMessage 函数实现,回到Service1.cs 修改一下OnStart 我们来打开一个CMD 窗口, ref si。
String pTitle, string lpApplicationName,右键属性查看其Session 状态, SetLastError = true, SetLastError = true)]public static extern bool DuplicateTokenEx( IntPtr hExistingToken, false);}[DllImport("kernel32.dll",而不是Session 0 中, SecurityIdentification,message, int Style, int MessageLength, SetLastError = true, out hToken);if (!result) { ShowMessageBox("WTSQueryUserToken failed"。
SetLastError = true)]public static extern int WTSGetActiveConsoleSessionId();[DllImport("wtsapi32.dll"。
SetLastError=true)]public static extern bool WTSQueryUserToken( Int32 sessionId, bool bWait); 在ShowMessageBox 函数中调用了WTSSendMessage 来发送信息窗口, CallingConvention = CallingConvention.StdCall)]public static extern bool CreateProcessAsUser( IntPtr hToken,它们之间加隔了一个保护墙,。
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/jiaob/c/11740.shtml
